home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DS-CD ROM 2 1993 August
/
DS CD-ROM 2.Ausgabe (August 1993).iso
/
programm
/
ds0256
/
mdebug22.exe
/
BSP.PRT
< prev
next >
Wrap
Text File
|
1992-11-01
|
51KB
|
1,741 lines
───────────────────────────────────────────────────────────────────
MDEBUG
Version V2.05
Highperformance Debugging Tool für PCs
Beispiele für die Nutzung von MDEBUG
Copyright 1992 by
Bernd Schemmer
All Rights reserved.
───────────────────────────────────────────────────────────────────
Credits
MDEBUG wurde geschrieben von Bernd Schemmer.
───────────────────────────────────────────────────────────────────
Copyright
MDEBUG ist Copyright 1992 by Bernd Schemmer
Dieses Dokument ist Copyright 1992 by Bernd Schemmer
───────────────────────────────────────────────────────────────────
Eingetragene Warenzeichen, Warennamen
Warenamen und eingetragene Warenzeichen werden in diesem Text ohne
Gewährleistung einer freien Verwendung benutzt.
Alle benutzten Warenanamen und eingetragenen Warenzeichen sind
Eigentum ihrer jeweiligen Besitzer.
───────────────────────────────────────────────────────────────────
Granatie-Ausschluß-Erklärung
Bernd Schemmer gibt keine Garantien irgendeiner Art, weder aus-
drücklich noch implizit, einschliesslich unbegrenzt aller Garantien
der Verwendbarkeit und/oder Nichtverwendbarkeit für irgendeinen
Zweck. Bernd Schemmer übernimmt keine Verpflichtungen für den
Gebrauchswert dieser Software über den Kaufpreis dieser Software
hinaus. Unter keinen Umständen ist Bernd Schemmer haftbar für
jedwede Folgeschäden, einschliesslich aller entgangenen Gewinne und
Vermögensverluste, oder anderer mittelbarer und unmittelbarer
Schäden, die durch den Gebrauch oder die Nichtverwendbarkeit
dieser Software und ihrer begleitenden Dokumentation entstehen.
Dies gilt auch dann, wenn Bernd Schemmer über die Möglichkeit
solcher Schäden unterrichtet war oder ist.
───────────────────────────────────────────────────────────────────
Inhalt Seite
────────────────────────────────────────────────────────────
Einleitung ........................................... 1
Verwendete Syntax in den Beispielen .................. 2
Allgemeine Hinweise zur Benutzung .................... 2
Tips für die Benutzung von MDEBUG .................... 2
Beispiele für die Interpreter-Befehle ................ 4
Normalisieren einer Adresse .......................... 4
Rechnen mit Zahlen in Doppelwortgröße ................ 4
Testen der Bits des Flag-Registers ................... 6
Setzen eines bestimmten Bits eines Registers ......... 6
Löschen eines bestimmten Bits eines Registers ....... 6
Invertieren eines bestimmten Bits eines Registers .... 6
Simulation von nicht implementierten
Maschinenbefehlen .................................... 7
Arbeiten mit Booleschen Werten ....................... 9
Ausführen von BIOS-Interrupts ........................ 10
Ermittlung des Tastaturcodes einer Taste ............. 10
Zeichen an den Drucker senden ........................ 10
Zeichenkette an den Drucker senden ................... 10
Ausführen von Funktionen des DOS-Interrupt 21h ....... 11
Belegung eines Extra-Speicherbereichs für Daten über
DOS .................................................. 11
Freigeben von Speicherblöcken ........................ 11
Ermitteln von Disketten/Platten-Werten ............... 11
Ermitteln der freien Diskkapazität ................... 12
Ermitteln der maximalen Diskkapazität ................ 12
Einrichten eines neuen Directorys .................... 13
Löschen eines Directorys ............................. 13
Wechseln des aktuellen Directorys .................... 13
Löschen einer Datei .................................. 13
Testen, ob eine Datei existiert ...................... 13
DOS-Speicherstrukturen anschauen oder ändern ......... 14
Durchlaufen der DPB-Kette (DOS 3.xx) ................. 14
Benutzung der SDL .................................... 15
Ermitteln der Anzahl der Einträge in der SDL ......... 17
Manipulieren der SDL ................................. 17
Durchlaufen der Kette der Puffer (nur DOS 3.xx) ...... 19
Ermitteln der Anzahl vorhandener Puffer .......... 19
────────────────────────────────────────────────────────────────────────────────
Inhalts-Verzeichnis I 1
Inhalt Seite
────────────────────────────────────────────────────────────
Ermitteln des Wertes von LASTDRIVE ................... 20
Durchlaufen der Kette der Device-Treiber ............. 21
Suchen des Device-Treibers für 'LPT1' ................ 21
Ermitteln aller freien Speicherblöcke ................ 22
Durchlaufen der MCB-Kette ............................ 22
Benutzung von MDEBUG für das Debuggen von eigenen
Programmen ........................................... 25
────────────────────────────────────────────────────────────────────────────────
Inhalts-Verzeichnis I 2
Einleitung
──────────
Diese Datei enthält Hinweise und Beispiele für die Benutzung von
MDEBUG. Hauptsächlich wird hier auf die Programmiersprache des
Interpreters eingegangen.
────────────────────────────────────────────────────────────────────────────────
Seite 1
Verwendete Syntax in den Beispielen
───────────────────────────────────
ALLE in den Beispielen angegebenen Werte ohne Angabe des Formats
sind hexadezimale Werte.
Alle Beispiele gehen davon aus, daß die Monitor-Start-Adresse aus
den Registern SE und OF ermittelt wird.
Das Zeichen '@' leitet Kommentare ein.
Hinweis:
Bei der Entwicklung von Befehlsketten die über den H- oder HN-
Befehl mehrfach ausgeführt werden sollen, ist es sinnvoll den H-
Befehl zuerst durch einen W-Befehl zu ersetzen und erst nach dem
Test den H- bzw. HN-Befehl einzusetzen.
Allgemeine Hinweise zur Benutzung
─────────────────────────────────
MDEBUG wurde nach der Philosophie
"Alles was machbar ist, ist erlaubt."
geschrieben. Der Anwender ist also für die Folgen seines Handelns
voll verantwortlich! MDEBUG selbst überprüft jeweils nur teilweise
die Syntax der Befehle. Mensch sollte sich also vor jeder Befehls-
Ausführung genau überlegen, was passieren kann!
Zu beachten ist auch, daß alle Speicher-Operationen mit Wort-Größen
im INTEL-Format (= Vertauschte Bytes) durchgeführt werden.
Die Vorzüge der Philosophie des Programmes überwiegen aber die
Nachteile bei falscher Benutzung, denke ich.
Tips für die Benutzung von MDEBUG
─────────────────────────────────
Fast alle Befehle sind mit allen Registern möglich. Es können also
auch Befehle, die der Prozessor normalerweise nicht beherrscht
(z.B. das Rechnen mit Segment-Registern) ausgeführt werden.
Zuweisungen der Form MOV [mem1],[mem2] sind ebenfalls möglich.
────────────────────────────────────────────────────────────────────────────────
Seite 2
Einzelne Werte können auch in den Hilfsregistern gespeichert
werden; kleinere Texte oder mehrere Werte können im nicht mehr
benötigtem PSP von MDEBUG zwischen CS:000h und CS:0100h gespeichert
werden. (siehe auch 'Programm-Interna')
Das PSP von MDEBUG (oder jeder beliebige andere Speicherbereich)
kann auch zum Zwischenspeichern von Befehlen genutzt werden.
Durch die Parameter '&name' und '*name' können im PSP gespeicherte
Befehlszeilen oder Daten auch in einer Datei gesichert werden bzw.
aus einer Datei restauriert werden.
Über die '#26'- und '#27'-Befehle kann der Eingabepuffer des
Interpreters auch zum Editieren und Verändern eines Strings (z.B.
aus dem Environment) benutzt werden.
Über den '#27'H-Befehl können auch mehr Befehle als in eine Zeile
passen auf einmal bearbeitet werden. Der W-Befehl, der H-Befehl,
der '#27'H-Befehl, der ¿-Befehl und der ¿H-Befehl ermöglichen es
zudem kleinere 'Routinen' auszuführen.
Mit dem Programm MDMKHLP.COM können eigene Hilfstextdateien für
die Online-Hilfe von MDEBUG erstellt werden.
(z.B. mit einem Hilfstext über die Datenstrukturen eines zu
untersuchenden Programmes, oder aus einem Teil der .LST-Datei des
Assemblers)
Alle Maschinen-Befehle können über den B- bzw. G-Befehl jederzeit
ausgeführt werden. Der jeweilige Maschinen-Code kann z.B aus einer
.LST-Datei eines Assemblers ermittelt werden.
Sinnvollerweise schreibt mensch den Code für den G-Befehl vorher
mit einen normalen Assembler, übersetzt diesen und benutzt das
Listing später zur Eingabe. Bzw. erstellt eine Datei der Maschinen-
codes als B-Befehl die dann über den Parameter '&name' in das
das PSP von MDEBUG eingelesen werden kann.
Kleinere Routinen können auch in übersetzter Form über den Para-
meter '&name' mit dem Schalter ',N' in das PSP eingelesen werden.
Dort können sie über den G-Befehl ausgeführt werden. Die so
geladenen Routinen dürfen aber nicht mit einem RET-Befehl enden!
────────────────────────────────────────────────────────────────────────────────
Seite 3
Beispiele für die Interpreter-Befehle
─────────────────────────────────────
Normalisieren einer Adresse
Normalisieren der Adresse in den Registern SE:OF. Nach der Norma-
lisierung hat das Register OF nur noch einen Wert zwischen 0h und
0Fh.
ADD SE,(OF » 4) ^ & OF,0F
Rechnen mit Zahlen in Doppelwortgröße
(hier in den Registern DX:AX)
■ Addition
ADD AX,2000 ^ ADD DX,FL%0 @ DX:AX <- DX:AX + 2000
oder
ADD AX,2000 ^ adc DX,0
Falls nach der ersten Addition das Carryflag gesetzt ist, ist ein
Übertrag vorhanden der auf das Highword (Register DX) aufaddiert
werden muß (zweiter ADD-Befehl bzw. adc-Befehl).
■ Subtraktion
SUB AX,2000 ^ SUB DX,FL%0 @ DX:AX <- DX:AX - 2000
oder
SUB AX,2000 ^ sbb DX,0
Falls nach der ersten Subtraktion das Carryflag gesetzt ist,
wurde noch eine Stelle geborgt, die von Highword (Register DX)
abezogen werden muß (zweiter SUB-Befehl bzw. sbb-Befehl)
────────────────────────────────────────────────────────────────────────────────
Seite 4
■ Multiplikationen bzw. Divisionen durch eine Zweierpotenz können
folgendermaßen programmiert werden:
Im Beispiel wird in CL jeweils die Zweierpotenz durch die geteilt
teilt bzw. multipliziert wird gespeichert.
MOV CL,3 @ Multiplikant = 2^3 = 8
< DX ^ < AX ^ ADD DX,FL%0 ^ - CL ^ ¿ CL ^ H
@ DX:AX <- DX:AX * 8
MOV CL,2 @ Divisor = 2^2 = 4
> AX ^ > DX ^ ADD AX,(FL%0 * 8000) ^ - CL ^ ¿ CL ^ H
@ DX:AX <- DX:AX / 4
■ Multiplikationen bzw. Divisionen durch eine andere Größe müssen
über den B-Befehl durchgeführt werden, wobei in den Beispielen
davon ausgegangen wird, daß diese Größe im Register CX steht.
Achtung:
Hier darf auf keinen Fall durch 0 geteilt werden! Bei verketteten
Befehlen sollte dies durch den Befehl '¿ CX' vor dem Divisionsbe-
fehl (mit dem Register durch das geteilt wird) verhindert werden.
■ Division
¿ CX ^ B F7,F1 @ AX <- (DX:AX DIV CX) und
@ DX <- (DX:AX MOD CX)
■ Multiplikation
B F7,E1 @ DX:AX <- AX * CX
────────────────────────────────────────────────────────────────────────────────
Seite 5
Testen der Bits des Flag-Registers
┌──────┬────────────────┬─────────────────────────────────────────┐
│ │ │ Test auf │
│ Bit │ Flag │ gesetztes Flag nicht gesetztes Flag │
╞══════╪════════════════╪═════════════════╤═══════════════════════╡
│ 00h │ Carry │ ¿ =(FL%0) │ ¿ (FL%0) │
│ 01h │ - │ │ │
│ 02h │ Parity (Even) │ ¿ =(FL%2) │ ¿ (FL%2) │
│ 03h │ - │ │ │
│ 04h │ Auxiliary │ ¿ =(FL%4) │ ¿ (FL%4) │
│ 05h │ - │ │ │
│ 06h │ Zero │ ¿ =(FL%6) │ ¿ (FL%6) │
│ 07h │ Sign │ ¿ =(FL%7) │ ¿ (FL%7) │
│ 08h │ Trap │ ¿ =(FL%8) │ ¿ (FL%8) │
│ 09h │ Interrupt │ ¿ =(FL%9) │ ¿ (FL%9) │
│ 0Ah │ Direction │ ¿ =(FL%0A) │ ¿ (FL%0A) │
│ 0Bh │ Overflow │ ¿ =(FL%0B) │ ¿ (FL%0B) │
│ 0Ch │ - │ │ │
│ 0Dh │ - │ │ │
│ 0Eh │ - │ │ │
│ 0Fh │ - │ │ │
└──────┴────────────────┴─────────────────┴───────────────────────┘
Da die unbenutzen Bits im Flag-Register vom Prozessor immer wieder
auf eins gesetzt werden, können sie leider nicht für eigene Zwecke
benutzt werden. Es kann aber ein Hilfsregister oder eine Speicher-
stelle als weiteres Flagregister benutzt werden, da der Test eines
Bits natürlich auch mit diesen möglich ist.
Setzen eines bestimmten Bits eines Registers
| AX,1«4 @ Setze Bit 4 von AX
Löschen eines bestimmten Bits eines Registers
& AX,(1«3)!-1 @ Lösche Bit 3 von AX
Invertieren eines bestimmten Bits eines Registers
! AX,1«7 @ Invertiere Bit 7 von AX
────────────────────────────────────────────────────────────────────────────────
Seite 6
Simulation von nicht implementierten Maschinenbefehlen
■ Simulation von REPNE SCASB
Damit AL durch die Subtraktion nicht verändert wird, wird hier
als erster Operand ein Ausdruck, dessen Wert gleich dem Inhalt
von AL ist, verwendet. Die Subtraktion verändert daher nur die
Flags (Benutzung des Pseudo-Registers). Da der erste Operand ein
Ausdruck ist (= Wort!), muß bei der Speicheradresse explizit das
Byte-Format angegeben werden. ES:DI zeigt nach der Ausführung
entweder auf das gefundene Zeichen oder auf das erste Zeichen
hinter dem String. (je nach Cursor-Position)
S AL+0,ES:*DI ^ ¿ 1-FL%6 ^ + DI ^ - CX ^ ¿ CX ^ H
───────────── ──────── ──── ───── ──── ─
Vergleich Wert gefunden? Zeiger Zähler CX=0? Schleife
(ZF = 1) erhöhen korrig. zuende?
■ Simulation von REPE SCASW
S AX+0,ES:DI ^ ¿ FL%6 ^ ADD DI,2 ^ - CX ^ ¿ CX ^ H
■ Simulation des Befehls CMP AX,BX
Damit AX nicht verändert wird, wird hier wieder das Pseudo-
Register benutzt, d.h. nach dem Befehl sind wie beim Original-
Befehl nur die Flags verändert.
S AX+0,BX
■ Simulation der Befehle SAHF und LAHF
Diese Befehle können nicht direkt simuliert werden, allerdings
kann der Wert des Flag-Registers durch einen einfachen MOV-Befehl
in ein anderes Register gesichert bzw. aus einem anderen Register
restauriert werden.
MOV AX,FL @ Save Flags in AX (SAHF)
MOV FL,AX @ Load Flags from AX (LAHF)
────────────────────────────────────────────────────────────────────────────────
Seite 7
■ Simulation des Befehls LDS SI,BX
MOV SI,DS:[BX] ^ MOV DS,DS:[BX+2]
■ Simulation des Befehls ROL AX,1
< AX ^ | AX,FL%0
■ Simulation des Befehls ROR AX,1
> AX ^ | AX,FL%0*8000
■ Simulation des Befehls XCHG AX,BX
! AX,BX ^ ! BX,AX ^ ! AX,BX
■ Simulation des Befehls XLATB
MOV AL,DS:[BX+AL]
■ Simulation der FOR-Schleife 'FOR CX=4 TO 9 BY 1 DO { AL = AL+5 }'
Vorbereitung:
MOV CX,4 @ Anfangswert ins Zählregister
Ausführung:
Im Beispiel wird nur AX jeweils um 5 erhöht. Der Endwert für
die Schleife ist hier 9, die Schleife soll 6 mal (9 - 4 + 1 )
durchlaufen werden.
ADD AL,5 ^ + CX ^ ¿ CX<(9+1) ^ H
──────────
Ausführen solange CX kleiner als der
Endwert+1 ist
■ Simulation der WHILE-Schleife 'WHILE (AL <> 0) DO { INC AX }'
¿ AL¬0 ^ + AX ^ H
■ Simulation der UNTIL-Schleife 'REPEAT { INC AX } UNTIL (AL = 0)'
+ AX ^ ¿ AL¬0 ^ H
oder
+ AX ^ ¿H AL=0
────────────────────────────────────────────────────────────────────────────────
Seite 8
Arbeiten mit Booleschen Werten
Die Operatoren '=', '<', '>', '¬' und '%' ergeben alle entweder
1 (= TRUE) oder 0 (= FALSE). Da der ¿- und der ¿H-Befehl einen
Booleschen Wert testen, können hiermit auch logische Verknüpfungen
programmiert werden. Es sollte allerdings darauf geachtet werden,
daß keinerlei Operator-Prioritäten vorhanden sind. (Alle Beispiele
ohne explizite Angabe gehen von vorzeichenlosen Werten aus.)
¿ AX=BX @ Bearbeitung fortsetzen,
@ falls AX = BX
¿ ((AX < BX) | (AX > BX)) @ Bearbeitung fortsetzen,
@ falls AX <> BX
@ (Simulation des Operators '¬')
¿ ((AX < BX) | (AX = BX)) @ '<='-Operator
¿ ( (AX < 8) & (AX > 1) ) @ Bearbeitung fortsetzen, falls AX
@ im Intervall 2 bis 7 (incl.) liegt
¿ ( (AX < 2) | (AX > 8) ) @ Bearbeitung fortsetzen, falls AX
@ nicht im Intervall 2 bis 8
@ (incl.) liegt
¿ ( AX%0 = 0 ) @ Bearbeitung fortsetzen, falls der
@ Wert aus AX gerade ist, d.h. das
@ 0-te Bit ist nicht gesetzt
¿ ( AX%0F = 0) @ Bearbeitung fortsetzen, falls der
@ vorzeichenbehaftete Wert aus AX
@ größer oder gleich 0 ist, d.h. das
@ 15-te Bit ist nicht gesetzt
¿ ( (DX > CX) | ( (AX > BX) & (DX = CX) ) )
@ Bearbeitung fortsetzen, falls das
@ Doppelwort in DX:AX größer als
@ das Doppelwort in CX:BX ist
────────────────────────────────────────────────────────────────────────────────
Seite 9
Ausführen von BIOS-Interrupts
Über den INT-Befehl kann jederzeit jeder beliebige BIOS-Interrupt
aufgerufen werden. Beachtet werden muß aber, daß verschiedene BIOS-
Routinen (z.B. des Interrupt 13h) NICHT reentrant sind!
Ermittlung des Tastaturcodes einer Taste
MOV AH,0 ^ INT 16 @ Funktion 0 des INT 16h ->> Taste lesen
@ entsprechende Taste drücken
AX enthält nun den vom Interrupt 16h gelieferten Tastatur-Code
Zeichen an den Drucker senden
MOV AL,'<zeichen>' @ AL mit dem zu sendenden Zeichen laden
MOV AH,0 @ AH mit der Funktions-Nummer laden
MOV DX,0 @ DX mit der Drucker-Nummer laden
@ (lpt1 = 0, lpt2 = 1, usw.)
INT 17 @ Drucker-Interrupt ausführen
@ AH enthält nun den Druckerstatus
Zeichenkette an den Drucker senden
Vorbereitung:
In einen freien Speicherbereich die gewünschte Zeichenkette
abgeschlossen mit einem Endemarker (hier ein Null-Byte) ein-
tragen und DS:BX auf die Adresse der Kette setzen.
(Ausgabe auf LPT1)
Ausführung:
M AL,DS:[BX] ^ ¿ AL¬0 ^ + BX ^ M AH,0 ^ M DX,0 ^ I 17 ^ H
──────────── ────── ────────────────────── ────
akt. Zeichen Ketten- Zeiger korrigieren und Zeichen
nach AL Ende ? Register laden drucken
────────────────────────────────────────────────────────────────────────────────
Seite 10
Ausführen von Funktionen des DOS-Interrupt 21h
Prinzipiell können aus MDEBUG heraus auch alle Funktionen des DOS-
Interrupts 21h ausgeführt werden. Da die meisten Funktionen des
Interrupt 21h NICHT reentrant sind, sollten Funktionen dieses
Interrupts aber nur ausgeführt werden, falls das (DOS-)Busy-Flag
von MDEBUG auf 0 steht. Ansonsten ist ein Systemabsturz nach dem
Ende des Aufrufs von MDEBUG sehr wahrscheinlich!
Belegung eines Extra-Speicherbereichs für Daten über DOS
MOV BX,0010 ^ MOV AH,48 ^ INT 21
@ BX = Größe des Speicherbereichs in
@ Paragraphen á 16 Byte; die Gesamtgröße
@ des zu belegenden Speichers ist also
@ 16*10h (= 16 dez) = 256 Byte (dez.)
Falls das Carry-Flag gelöscht ist, enthält AX nun das Segment des
belegten Speicherbereichs, andernfalls enthält BX die Größe des
größten freien Speicherbereichs in Paragraphen. Die Adresse aus
AX muß im Erfolgsfall (z.B.) in einem Hilfsregister gespeichert
werden, da dieser Speicherbereich vor dem Entfernen von MDEBUG aus
dem Speicher wieder freigegeben werden sollte. Nach diesem Befehl
muß der Besitzer im neuen MCB (Segment = AX-1, Besitzer = Wort am
Offset 1) korrigiert werden (z.B. PSP von MDEBUG eintragen).
Freigeben von Speicherblöcken
MOV ES,freizugebendes_Segment ^ MOV AH,49 ^ INT 21
Ermitteln von Disketten/Platten-Werten
Hinweis:
Falls die Werte einer Diskette ermittelt werden sollen, sollte auch
eine Diskette im geschlossenen Diskettenlaufwerk sein (sonst wird
der Interrupt 24h aufgerufen)!
────────────────────────────────────────────────────────────────────────────────
Seite 11
Ermitteln der freien Diskkapazität
MOV AH,36 ^ MOV DL,0 ^ INT 21
@ DL = Laufwerknummer, 0 = akt. LW,
@ 1 = Lw. A, 2 = Lw B, etc.
Falls AX = 0FFFF wurde eine unbekannte Laufwerksnummer angegeben.
Sonst kann die freie Diskkapazität ermittelt werden durch:
MOV DX,0
B F7,E1 @ MUL CX
B F7,E3 @ MUL BX
@ DX:AX enthält die freie Kapazität
@ in Bytes (als Doppelwort)
Ermitteln der maximalen Diskkapazität
MOV AH,36 ^ MOV DL,0 ^ INT 21
@ DL =Laufwerknummer, 0 = akt. LW,
@ 1 = Lw. A, 2 = Lw B, etc.
Falls AX = 0FFFF wurde eine unbekannte Laufwerksnummer angegegeben.
Sonst kann die Diskkapazität ermittelt werden durch:
MOV BX,DX @ Anzahl Cluster nach BX
B F7,E1 @ MUL CX -> DX:AX = Bytes/Cluster
B F7,E3 @ MUL BX -> DX:AX enthält nun die max.
@ Kapazität in Bytes (als Doppelwort)
Sinnvollerweise teilt mensch den erhaltenen Wert durch 1024 um den
Wert in KB zu erhalten und somit in einem Register darstellen zu
können:
MOV BX,#1024 ^ B F7,F3 @ DIV BX (=1024)
MOV R8,AX @ R8 = max. Diskkapazität in KB
────────────────────────────────────────────────────────────────────────────────
Seite 12
Falls die im Kommandotreiber MDBSPDRV.COM implementierten Befehle
zur Datei- und Directorybehandlung nicht angewendet werden können,
können diese folgendermaßen programmiert werden:
Für alle folgenden Beispiele auf dieser Seite gilt:
Vor der Ausführung der Befehle muß der Name des Directorys bzw. der
Datei abgeschlossen mit einem Null-Byte in einem freien Speicherbe-
reich eingetragen werden.Die Adresse des Namens muß in die Register
DS (Segment) und DX (Offset) eingetragen werden.
Falls nach der Ausführung das Carry-Flag gelöscht ist, war die
Aktion erfolgreich.
Andernfalls trat ein Fehler auf und das Register AX enthält die
DOS-Fehlernummer.
Einrichten eines neuen Directorys
MOV AH,39 ^ INT 21
Löschen eines Directorys
MOV AH,3A ^ INT 021
Wechseln des aktuellen Directorys
MOV AH,3B ^ INT 021
Löschen einer Datei
MOV AH,41 ^ INT 021
Testen, ob eine Datei existiert
MOV AX,4300 ^ INT 021 @ CF = 0 ->> CX = Dateiattribut
────────────────────────────────────────────────────────────────────────────────
Seite 13
DOS-Speicherstrukturen anschauen oder ändern
Durchlaufen der DPB-Kette (DOS 3.xx)
Im Interpeter durch den Befehl
D M3
die Monitor-Start-Adresse ändern. Der Monitor zeigt nun den ersten
DPB an. Da das Verkettungs-Feld der DPBs nicht am Offset 0h sondern
beim Offset 18h beginnt, wird für das Durchlaufen der DPBs ein
verketteter Befehl oder ein Ausdruck benötigt:
ADD OF,18 ^ P OF
oder:
P [OF+18]
Durch Betätigen von <CTRL-RETURN> kann jetzt im Interpreter die
Kette der DPBs durchlaufen werden.
Unter Zuhilfename des W-Befehls lautet die Befehlszeile:
ADD OF,18 ^ P OF ^ W
oder:
P [OF+18] ^ MOV BX,[OF+18] ^ ¿ (BX+1) ^ W
Durch die Eingabe von <Backspace> auf dem W-Befehl wird jeweils der
nächste DPB angezeigt.
Hinweis:
Der letzte DPB hat als Offset im Verkettungsfeld beim Offset 18h
den Wert 0FFFFh stehen. Deshalb beendet (0FFFFh = -1 -> -1 + 1 = 0)
die Ausführung.
────────────────────────────────────────────────────────────────────────────────
Seite 14
Benutzung der SDL
■ Ermittlung der Datei bzw. des Geräts dem ein Handle zugeordnet
ist über die SDL.
Zuerst muß über die Befehle
MOV AH,062 ^ I 21 ^ MOV SE,BX ^ MOV OF,0
das aktuelle PSP im Monitor angezeigt werden. Da diese Funktion des
Interrupts 21h reentrant ist, kann sie jederzeit ausgeführt werden.
Danach wird durch die Befehle
MOV CX,[OF+32] ^ P OF+34
das Register CX mit der maximal möglichen Anzahl Handles geladen
und die akt. lokale Handle-Tabelle im Monitor angezeigt. Falls der
Wert im Register CX kleiner als das zu untersuchende Handle ist,
ist dieses nicht bekannt (d.h. für den akt. Prozess unbelegt).
Ansonsten kann jetzt über den Befehl
MOV BL,[OF+HandleNummer] ^ MOV BH,0
das gewünschte Handle in das DOS-interne Handle konvertiert werden.
Falls dabei für BX der Wert 00FFh herauskommt, ist das angegebene
Handle für den akt. Prozess noch nicht belegt.
Andernfalls kann danach über den Befehl
D M4 ^ MOV CX,[OF+04]
die erste Teilliste der SDL im Monitor angezeigt und CX mit der
Anzahl Elemente in dieser Teilliste geladen werden.
Jetzt muß überprüft werden, ob der Wert in CX größer als das
ermittelte DOS-interne Handle ist oder nicht. Falls dies der Fall
ist, muß zuerst über den Befehl
P OF
die zweite Teilliste der SDL im Monitor angzeigt werden. (Ansonsten
kann dieser Befehl entfallen)
Durch den Befehl
ADD OF,6
muß nun der Header der Teilliste der SDL überlesen werden und durch
den Befehl
ADD OF,(BX*#53)+20 @ DOS 3.xx
bzw.
ADD OF,(BX*#59)+20 @ DOS 4.+
wird im Monitor beim Offset SE:OF der Name des zugeordneten Gerätes
bzw. der zugeordneten Datei angezeigt.
────────────────────────────────────────────────────────────────────────────────
Seite 15
Graphisch dargestellt sieht das Ganze dann folgendermaßen aus:
Interrupt 21h mit AH = 62h -> Ausgabe: BX = Zeiger auf akt.
║ PSP (Segment=BX,
╔══════════════════════════════════════════╝ Offset=0)
║ ┌── Länge der lokalen Handle-Tabelle
║ │ ┌── Adresse der lokalen Handle-
║ │ │ Tabelle
║ Offset 32h Offset 34h
║ ┌────┬────┬─────┬──────┬───────────┬───┐
╚═>│ CD │ 20 │ ... │ mmmm │ seg:off │...│ akt. PSP des Programms
└────┴────┴─────┴──────┴───────────┴───┘
║
╔══════════════════════════════════╝
║┌─ Rückgabe der Routinen zur Dateiverarbeitung (Eröffnung) mit Handles
║│ ┌──> Handle für Routinen zur Dateiverarbeitung mit Handles
║│ │
║└> Index: >───┘ 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13
║ Inhalt z.B.: ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
╚══════════════>│01│01│01│00│02│-1│-1│-1│-1│-1│-1│-1│-1│-1│-1│-1│-1│-1│-1│-1│
┌─<└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┘
│ ^ ^ ^ ^ ^ ^ ...
│ │ │ │ │ │ └ Ab hier folgen die Handle
│ │ │ │ │ │ für Benutzer-Definierte Dateien
│ └──┴──┴──┴──┴─ vordefinierte Handles
┌─────────────┘
└────> Der Eintrag des Tabellen-Elementes mit dem gewünschten Index
wird nun als Index für die System-Datei-Liste (SDL) genommen
in deren Einträgen jeweils beim Offset 20h der Name des
Gerätes bzw. der Datei steht.
1. Teilliste der SDL
┌───────────────────────────────────────────────────────────┐
│ Zeiger auf die 2. Teilliste des SDL │══╗
├───────────────────────────────────────────────────────────┤ ║
│ Anzahl Einträge in dieser Teilliste (normalerweise 5) │ ║
├───────────────────────────────────────────────────────────┤ ║
│ 1. Eintrag in dieser Teilliste (= 0. Eintrag gesamt) │ ║
│ ... │ ║
│ Letzter Eintrag in dieser Teilliste (= 4. Eintrag gesamt) │ ║
└───────────────────────────────────────────────────────────┘ ║
╔═════════════════════════════════════════════════════════════════╝
║ 2. Teilliste der SDL
║ ┌───────────────────────────────────────────────────────────┐
╚═>│ Zeiger auf die nächste Teilliste, normalerweise FFFF:FFFF │
├───────────────────────────────────────────────────────────┤
│ Anzahl Einträge in dieser Teilliste (Anz.= FILES - 5) │
├───────────────────────────────────────────────────────────┤
│ 1. Eintrag in dieser Teilliste (= 5. Eintrag gesamt) │
│ ... │
│ Letzter Eintrag in dieser Teilliste (= n. Eintrag gesamt │
│ mit n = FILES - 1) │
└───────────────────────────────────────────────────────────┘
────────────────────────────────────────────────────────────────────────────────
Seite 16
Ermitteln der Anzahl der Einträge in der SDL
(= FILES aus der Datei CONFIG.SYS, Vorr.: keine individuelle Ver-
längerung der SDL in Kraft und FILES nicht im EMS installiert)
MOV CX,0 ^ D M4 ^ A CX,[OF+4] ^ P OF ^ ADD CX,[OF+4]
In CX steht nun die gewünschte Anzahl.
Manipulieren der SDL
Beispiel:
Nach mehreren Debugger-Sitzungen, bei denen jeweils Dateien eröff-
net, aber nicht wieder geschlossen wurden, tritt der DOS-Fehler
'Kein freies Handle mehr' auf, d.h. die SDL enthält keine freien
Einträge mehr.
In diesem Fall kann von versierten(!) Programmierern mit Hilfe von
MDEBUG die interne System-Datei-Liste korrigiert werden:
Zuerst muß hierfür im Interpreter durch den Befehl
D M4
die erste Teilliste der SDL im Monitor angezeigt werden.
Da die nun angezeigte erste Teilliste der SDL im Normalfall nur die
Einträge für die Systemdateien/geräte (CON, LPT1, COM1, usw.) ent-
hält, sollten in dieser Liste keine Änderungen vorgenommen werden.
Der Befehl
P OF
führt deshalb zur Anzeige der zweiten Teilliste der SDL.
Beim Offset OF+4 steht die Anzahl der Einträge in dieser Liste (als
Wortgröße), die mensch sich mit dem Befehl
MOV R7,[OF+4]
im Register R7 merken sollte.
────────────────────────────────────────────────────────────────────────────────
Seite 17
Hinweis:
Falls beim Offset OF ein Doppelwort mit Offset und Segment ungleich
0FFFFh steht, ist dies ein Zeiger auf eine weitere Teilliste.
Nun kann mit dem Befehl
ADD OF,6
der nicht mehr benötigte Header der Teilliste überlesen werden.
SE:OF zeigt nun auf den 1. Eintrag in der Teilliste der SDL. Beim
Offset OF+20h steht der Name der Datei (bzw. des Gerätes) der (dem)
dieser Eintrag zugeordnet ist.
Der Wert am Offset OF bestimmt, ob der Eintrag belegt (wert <> 0 =
Anzahl der Verweise auf diesen Eintrag) oder frei (wert=0) ist. Der
Wert am Offset OF+02h bestimmt, ob die Datei zum Lesen (wert=0),
zum Schreiben (wert=1) oder zum Lesen und Schreiben (wert=2)
geöffnet ist.
Falls der Eintrag nicht mehr benötigt wird, kann er durch den
Befehl
MOV [OF],0
gelöscht werden.
Falls mehrere Einträge gelöscht werden sollen, bietet sich folgende
Befehlskette an:
ADD OF,35 ^ - R7 ^ W ^ MOV [OF],0 ^ ¿ R7 ^ H @ DOS 3.xx
bzw.
ADD OF,3B ^ - R7 ^ W ^ MOV [OF],0 ^ ¿ R7 ^ H @ DOS 4+
Zuerst wird der Monitor auf die Adresse des nächsten Eintrags
gesetzt und dann über den W-Befehl angezeigt. Die Eingabe von <ESC>
bricht die weitere Ausführung der Befehlszeile nun ab, d.h. der
Eintrag wird NICHT gelöscht; die Eingabe von <Backspace> verhindert
ebenfalls die Löschung des Eintrags allerdings wird sofort der
nächste Eintrag angezeigt. Jede andere Taste führt zur Löschung des
Eintrages und zur Anzeige des nächsten Eintrages. Die SDL kann so
bequem durchlaufen werden, wobei das Hilfsregister R7 als Zähler
dient. Der Befehl '¿ R7' beendet dann die Ausführung nach den
letzten Eintrag.
Allerdings können hier durch das Schließen von Dateien, die zum
Schreiben auf waren, oder bei geladener Netzwerksoftware Daten-
verluste auftreten!
────────────────────────────────────────────────────────────────────────────────
Seite 18
Durchlaufen der Kette der Puffer (nur DOS 3.xx)
Im Interpreter durch den Befehl
D M7
den Monitor auf die Adresse des ersten Puffers in der Kette setzen.
Danach den Interpreter durch die Taste <ESC> verlassen. Der Cursor
steht jetzt auf dem Verkettungs-Feld des ersten Puffers, so daß
die Kette der Puffer durch Eingabe von <P> im Monitor durchlaufen
werden kann.
Im Interpreter lautet der Befehl zur Anzeige des jeweils nächsten
Puffers:
P OF
Unter Zuhilfenahme des W- und ¿-Befehls kann folgende Befehlskette
benutzt werden:
P OF ^ MOV BX,[OF] ^ ¿ (BX+1) ^ W
Durch die Eingabe von <Backspace> auf den W-Befehl wird jeweils der
nächste Puffer angezeigt. Der ¿-Befehl beendet die Ausführung nach
dem letzten Puffer, da der letzte Puffer als Offset im Verkettungs-
Feld -1 (= 0FFFFh) stehen hat.
Ermitteln der Anzahl vorhandener Puffer
(= BUFFERS aus der Datei CONFIG.SYS, nur bei DOS 3.xx)
Vorbereitung:
D M7 ^ MOV CX,0
Ausführung:
+ CX ^ MOV AX,[OF] ^ ¿ AX+1 ^ P OF ^ H
In CX steht nun die Anzahl vorhandener Puffer.
────────────────────────────────────────────────────────────────────────────────
Seite 19
■ Testen, ob der Sektor 003 des Laufwerks D: in einem Puffer vor-
liegt (nur DOS 3.xx)
Vorbereitung:
(BX = Sektornummer,
CL = Laufwerknummer, wobei A = 0, B = 1, C = 2 usw.):
D M7 ^ MOV BX,0003 ^ MOV CL,'D'-'A'
Ausführung:
(damit die Befehlszeile auf einmal eingegeben werden kann,
sind alle unnötigen Trennzeichen weggelassen worden)
M AX,[OF^¿ AX+1^M AX,[OF+6^M CH [OF+4^¿ =((AX=BX)&(CL=CH))^P OF^H
SE:OF zeigt nach dem Ende der Befehlszeile entweder auf den betref-
fenden oder den letzten Puffer. Der Cursor steht im ersten Fall
hinter dem zweiten ¿-Befehl, im zweiten Fall hinter dem ersten
¿-Befehl.
Ermitteln des Wertes von LASTDRIVE
D M0 ^ MOV 8L,[OF+29] ^ ADD 8L,'@'
oder (ohne Veränderung des Monitors, DOS-Busy-Flag = 0!):
MOV AH,52 ^ I 21 ^ MOV 8L,ES:[BX+21] ^ ADD 8L,'@'
Das Register 8L (= Lowbyte von R8) enthält nun den Buchstaben des
letzten möglichen logischen Laufwerkes.
■ Ermitteln des physikalischen Pfades des logischen Laufwerkes O:
(Vorr.: Der bei LASTDRIVE in der Datei CONFIG.SYS angegebene
Wert ist größer oder gleich 'O'!)
D M8 ^ ADD OF,('O'-'A')*51 @ DOS 3.xx
bzw.
D M8 ^ ADD OF,('O'-'A')*58 @ DOS 4.+
SE:OF zeigt nun auf den physikalischen Pfad für das logische Lauf-
werk 'O:'. Falls im Byte mit dem Offset OF+44 das Bit Nr. 6 nicht
gesetzt ist, ist das Laufwerk nicht bekannt.
────────────────────────────────────────────────────────────────────────────────
Seite 20
Durchlaufen der Kette der Device-Treiber
Vorbereitung:
D M0 ^ A OF,2A ^ M CX,0 @ -> SE:OF zeigt auf das NUL-Device
@ -> CX = Zähler für die Devices
Ausführung:
+ CX ^ P OF ^ MOV AX,[OF] ^ ¿ AX+1 ^ W
Nach Eingabe von <Backspace> auf den W-Befehl wird jeweils der Kopf
jedes Treibers angezeigt.
Nach Beenden der Befehlskette durch den ¿-Befehl zeigt SE:OF auf
den letzten Treiber und CX enthält die Anzahl der geladenen Treiber.
Suchen des Device-Treibers für 'LPT1'
Vorbereitung:
D M0 ^ ADD OF,2A ^ MOV DX,'PL' ^ MOV CX,'1T'
@ -> SE:OF zeigt auf das NUL-Device
@ -> DX:CX = Suchstring
Ausführung
(der erste Treiber ist immer das NUL-Device und kann also
überlesen werden. Damit die Befehlszeile auf einmal eingege-
ben werden kann sind alle unnötigen Trennzeichen weggelassen
worden)
P OF^M AX,[OF+A^M BX,[OF+C^¿ =((AX=DX)&(BX=CX))^M AX,[OF^¿ AX+1^H
Nach Beenden der Befehlskette durch den ¿-Befehl zeigt SE:OF ent-
weder auf den Treiber für 'LPT1' oder auf den letzten Treiber (je
nachdem hinter welchen ¿-Befehl der Cursor steht).
────────────────────────────────────────────────────────────────────────────────
Seite 21
Ermitteln aller freien Speicherblöcke
Vorbereitung:
D M2
Ausführung:
M AL,[OF] ^¿ AL-'Z' ^A SE,[OF+3] ^+ SE ^M AX,[OF+1] ^¿ AX¬0 ^H
Die Ausführung der Befehlskette wird bei jeden Erreichen eines
freien Speicherblocks unterbrochen. Nach einer Unterbrechung kann
die Ausführung durch <CTRL-RETURN> fortgesetzt werden.
Der Befehl ' ¿ AL-'Z' ' verhindert die Fortsetzung falls der letzte
Block erreicht ist, da dieser als Kennzeichen das Zeichen 'Z' be-
sitzt. Bei allen anderen Blöcken ist das Kennzeichen 'M'.
Durchlaufen der MCB-Kette
Im Interpreter den Befehl
D M2
eingeben, diesen über die Taste <ESC> verlassen und die Taste
<Home> betätigen.
Oder im Monitor auf einem Byte, das nicht den Wert 04Dh (= 'M')
enthält, die Taste <M> betätigen.
Die Kette der MCBs kann nun im Monitor durch wiederholte Eingabe
der Taste <M> durchlaufen werden.
Im Interpreter kann die Kette der MCBs durch folgende Befehle
durchlaufen werden:
ADD OF,3 ^ ADD SE,[OF] ^ + SE ^ MOV OF,0 ^ W
oder:
ADD SE,[OF+3] ^ + SE ^ M BL,[OF] ^ ¿ (BL-'Z') ^ W
Durch die Eingabe von <Backspace> auf den W-Befehl wird nun die
Kette der MCBs durchlaufen. Der ¿-Befehl beendet die Ausführung
nach dem letzten MCB.
────────────────────────────────────────────────────────────────────────────────
Seite 22
■ Durchlaufen der Kette der MCBs im Interpreter mit Anzeige der
Besitzer jedes Blocks
Vorbereitung:
D M2 ^ MOV R7,SE @ R7 = Zwischenspeicher für akt. MCB
Die Kette der MCBs kann nun durch folgende Befehlsfolge, unter
Anzeige der Besitzer der Blöcke, durchlaufen werden:
M SE,R7^A SE,[OF+3]^+ SE^M R7,SE^W^ M SE,SE+1:[2C]^W
─────── ──────────────── ─────── ─ ────────────── ─
(1) (2) (3) (4) (5) (6)
Durch den Befehl 'M SE,R7' (1) wird zuerst der Monitor auf die
Adresse des aktuellen MCB gesetzt. Danach wird durch die Befehle
'A SE,[OF+3] ^ + SE' (2) im Register SE die Adresse des nächsten
MCB ermittelt. Durch den Befehl 'M R7,SE' (3) wird diese dann im
Register R7 gesichert. Der MCB wird nun angezeigt (4). Falls auf
den W-Befehl (4) die Taste <Backspace> betätigt wird, wird sofort
der nächste MCB angezeigt. Jede andere Taste, außer <ESC> führt
dazu, daß über die Befehls-Folge 'M SE,SE+1:[2C]' (5) zuerst der
dem Block zugehörige Environmentblock angezeigt wird. Falls auf den
zweiten W-Befehl (6) <Backspace> betätigt wird, wird der nächste
MCB angezeigt. Da nur Hauptblöcke ein Environment haben, ist die
Eingabe von <Backspace> auf den ersten W-Befehl (4) nur sinnvoll
wenn das Wort am Offset OF+1 ungleich Null (Block ist frei) und un-
gleich 08 (Block gehört zu DOS) ist.
Außerdem muß der Wert beim Offset OF+1 gleich SE+1 sein, da der
Block sonst kein Hauptblock ist. Die Eingabe einer anderen Taste
als <ESC> oder <Backspace> auf den ersten W-Befehl, falls diese
Bedingungen nicht erfüllt sind, zeigt nur unsinnige Daten an.
────────────────────────────────────────────────────────────────────────────────
Seite 23
Graphisch dargestellt ergibt sich also bei der Annahme das der zu
untersuchende MCB einem Programm gehört, daß sein Environment noch
nicht freigegeben hat, folgendes:
zu untersuchender MCB (1)
┌─> Länge des zugehörigen Blocks
│
┌───┬──────┬──────┬──────────────────────────┐
│ M │ nnnn │ mmmm │ bei DOS 3.xx freier Rest │
└───┴──────┴──────┴──────────────────────────┘
║
╔═════════╝
║
║ MCB des Hautpblocks (2)
║ ┌───┬──────┬──────┬──────────────────────────┐
║ │ M │ nnnn │ mmmm │ bei DOS 3.xx freier Rest │
║ └───┴──────┴──────┴──────────────────────────┘
║ ║
╠<═════════╝
╠<═══════════════════════════════════════════════════╗
║ PSP des Hauptblocks (folgt direkt auf den MCB 2)║
║ Offset 2Ch ║
║ ┌────┬────┬─────┬──────┬───┐ ║
╚══>│ CD │ 20 │ ... │ nnnn │...│ ║
└────┴────┴─────┴──────┴───┘ ║
║ ║
╔══════════════════════╝ ║
║ MCB des Environments des Hauptblocks (3) ║
║ ┌───┬──────┬──────┬──────────────────────────┐ ║
║ │ M │ nnnn │ mmmm │ bei DOS 3.xx freier Rest │ ║
║ └───┴──────┴──────┴──────────────────────────┘ ║
║ ║ ║
║ ╚═════════════════════════════════════════╝
║
║ Environment des Hauptblocks (folgt direkt auf den MCB 3)
║ ┌──────┬──────┬──────────────────────────────┐
╚══>│ ... │ 0001 │ Name des Besitzers │
└──────┴──────┴──────────────────────────────┘
Hierbei können die MCBs 1 und 2 oder 1 und 3 jeweils identisch
sein.
────────────────────────────────────────────────────────────────────────────────
Seite 24
Benutzung von MDEBUG für das Debuggen von eigenen Programmen
────────────────────────────────────────────────────────────
MDEBUG eignet sich am besten zur Anzeige und Manipulation von
Datenstrukturen von Programmen.
MDEBUG kann zum Debuggen von eigenen Programmen benutzt werden
indem an den zu überprüfenden Stellen der Code zum Aufruf des User-
Ints von MDEBUG eingefügt wird.
Falls verschiedene Variablen des Programmes untersucht werden
sollen, können die Adressen dieser vorher in die Prozessor-Register
geladen werden oder aber über den Aufruf der Funktion 01h des User-
Ints in die Hilfsregister von MDEBUG geladen werden.
(siehe TESTMD.PAS).
Falls in den Registern SS oder SP Parameter übergeben werden,
sollte in MDEBUG vor der Änderung dieser Register KEIN B-, I-, C-
oder G-Befehl ausgeführt werden!
Der aktuelle User-Int von MDEBUG sollte nicht als Konstante einge-
tragen, sondern während der Laufzeit ermittelt werden.
Turbo-Pascal 5.0 z.B. mißbraucht den Interrupt 60h in der Entwick-
lungsumgebung für eigene Zwecke, so daß, falls der Interrupt 60h
als User-Int von MDEBUG installiert ist, ein Aufruf des User-Int
aus der Entwicklungsumgebung heraus zum Systemabsturz führt!
────────────────────────────────────────────────────────────────────────────────
Seite 25